<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <p data-lake-id="u090d483d" id="u090d483d"><span data-lake-id="u7aa8f91d" id="u7aa8f91d">序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道，Java对象是保存在JVM的堆内存中的，也就是说，如果JVM堆不存在了，那么对象也就跟着消失了。</span></p>
  <p data-lake-id="u4e74a710" id="u4e74a710"><span data-lake-id="u16ead768" id="u16ead768">​</span><br></p>
  <p data-lake-id="uf34eb054" id="uf34eb054"><span data-lake-id="uef679e9a" id="uef679e9a">而序列化提供了一种方案，可以让你在即使JVM停机的情况下也能把对象保存下来的方案。就像我们平时用的U盘一样。</span></p>
  <p data-lake-id="u2196008c" id="u2196008c"><span data-lake-id="u95a6172c" id="u95a6172c">​</span><br></p>
  <p data-lake-id="ube040e3a" id="ube040e3a"><span data-lake-id="u1c90ec44" id="u1c90ec44">把Java对象序列化成可存储或传输的形式（如二进制流），比如保存在文件中。这样，当再次需要这个对象的时候，从文件中读取出二进制流，再从二进制流中反序列化出对象。</span></p>
  <p data-lake-id="u2c042c04" id="u2c042c04"><span data-lake-id="ua6cbcf7f" id="ua6cbcf7f">​</span><br></p>
  <p data-lake-id="u27ea8a57" id="u27ea8a57"><span data-lake-id="uaf356df4" id="uaf356df4">但是，</span><strong><span data-lake-id="u99c84f0c" id="u99c84f0c">虚拟机是否允许反序列化，不仅取决于类路径和功能代码是否一致，一个非常重要的一点是两个类的序列化 ID 是否一致，即serialVersionUID要求一致。</span></strong></p>
  <p data-lake-id="u2c35b16d" id="u2c35b16d"><span data-lake-id="uf44e3e2f" id="uf44e3e2f">​</span><br></p>
  <p data-lake-id="ue4231d53" id="ue4231d53"><span data-lake-id="u307ca197" id="u307ca197">在进行反序列化时，JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较，如果相同就认为是一致的，可以进行反序列化，否则就会出现序列化版本不一致的异常，即是InvalidCastException。这样做是为了保证安全，因为文件存储中的内容可能被篡改。</span></p>
  <p data-lake-id="uc8922756" id="uc8922756"><span data-lake-id="ua2481b11" id="ua2481b11">​</span><br></p>
  <p data-lake-id="u7b7acf98" id="u7b7acf98"><span data-lake-id="u6850800a" id="u6850800a">当实现java.io.Serializable接口的类没有显式地定义一个serialVersionUID变量时候，Java序列化机制会根据编译的Class自动生成一个serialVersionUID作序列化版本比较用，这种情况下，如果Class文件没有发生变化，就算再编译多次，serialVersionUID也不会变化的。但是，如果发生了变化，那么这个文件对应的serialVersionUID也就会发生变化。</span></p>
  <p data-lake-id="u33b1cd9c" id="u33b1cd9c"><span data-lake-id="u5236253d" id="u5236253d">​</span><br></p>
  <p data-lake-id="ub8a532ec" id="ub8a532ec"><span data-lake-id="ua76625aa" id="ua76625aa">基于以上原理，如果我们一个类实现了Serializable接口，但是没有定义serialVersionUID，然后序列化。在序列化之后，由于某些原因，我们对该类做了变更，重新启动应用后，我们相对之前序列化过的对象进行反序列化的话就会报错。</span></p>
 </body>
</html>